/*
 * @Title XmlDemo.java
 * @Description
 * @Copyright Copyright(c) 2018
 * @Company com.lizhen
 * @author lizhen
 * @version 0.0.1
 */
package com.lizhen.core.function.xml;

import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.*;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * @author lizhen
 */
public class XmlDemo {

    private static final String FILE_PATH = "1.8\\api\\main\\resource\\com\\lizhen\\core\\function\\xml\\XmlDemo\\bookstore.xml";

    /**
     * @author lizhen
     */
    public XmlDemo() {
    }

    /**
     * @author lizhen
     */
    public static void main(String[] args) {
        DomDemo.main(null);
        SaxDemo.main(null);
        JDom.main(null);
        Dom4j.main(null);
        Stax.main(null);
        XPath.main(null);
    }

    static class DomDemo {

        public static void main(String[] args) {
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            try {
                DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
                Document document = documentBuilder.parse(FILE_PATH);
                NodeList bookList = document.getElementsByTagName("book");

                System.out.println("总共有" + bookList.getLength() + "本书");
                for (int i = 0; i < bookList.getLength(); i++) {
                    System.out.println("开始 当前是第" + (i + 1) + "本书");

                    Node book = bookList.item(i);
                    NamedNodeMap attrs = book.getAttributes();

                    System.out.println("第" + (i + 1) + "本书总共有" + attrs.getLength() + "个属性");
                    for (int j = 0; j < attrs.getLength(); j++) {
                        Node attr = attrs.item(j);
                        System.out.print("属性名是" + attr.getNodeName());
                        System.out.println(" 属性值是ֵ" + attr.getNodeValue());
                    }

                    NodeList childNodes = book.getChildNodes();

                    System.out.println("第" + (i + 1) + "本书总共有" + childNodes.getLength() + "个子元素");
                    for (int k = 0; k < childNodes.getLength(); k++) {
                        if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
                            System.out.print("第" + (k + 1) + "个元素属性名是" + childNodes.item(k).getNodeName());
                            System.out.println(" 属性值是" + childNodes.item(k).getFirstChild().getNodeValue());
                            System.out.println("子元素内容是" + childNodes.item(k).getTextContent());
                        }
                    }
                    System.out.println("结束 当前是第" + (i + 1) + "本书");
                }
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }
    }

    static class SaxDemo extends DefaultHandler {

        String value = null;
        SaxBook book = null;
        int bookIndex = 0;
        private ArrayList<SaxBook> bookList = new ArrayList<>();

        public static void main(String[] args) {
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            try {
                SAXParser saxParser = saxParserFactory.newSAXParser();
                SaxDemo saxDemo = new SaxDemo();
                saxParser.parse(FILE_PATH, saxDemo);

                System.out.println("总共有" + saxDemo.getBookList().size() + "本书");
                for (SaxBook book : saxDemo.getBookList()) {
                    System.out.println(book.getId());
                    System.out.println(book.getName());
                    System.out.println(book.getAuthor());
                    System.out.println(book.getYear());
                    System.out.println(book.getPrice());
                    System.out.println(book.getLanguage());
                    System.out.println("----finish----");
                }
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }

        public ArrayList<SaxBook> getBookList() {
            return bookList;
        }

        @Override
        public void startDocument() {
            System.out.println("startDocument");

            try {
                super.startDocument();
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void endDocument() {
            try {
                super.endDocument();

                System.out.println("endDocument");
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) {
            try {
                super.startElement(uri, localName, qName, attributes);

                if (qName.equals("book")) {
                    bookIndex++;
                    book = new SaxBook();

                    System.out.println("book元素解析开始");
                    int num = attributes.getLength();
                    for (int i = 0; i < num; i++) {
                        System.out.print("book第" + (i + 1) + "个属性名是" + attributes.getQName(i));
                        System.out.println(" 属性值是" + attributes.getValue(i));

                        if (attributes.getQName(i).equals("id")) {
                            book.setId(attributes.getValue(i));
                        }
                    }

                } else if (!qName.equals("name") && !qName.equals("bookstore")) {
                    System.out.print("当前元素名是" + qName + " ");
                }
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void endElement(String uri, String localName, String qName) {
            try {
                super.endElement(uri, localName, qName);
                if (qName.equals("book")) {
                    bookList.add(book);
                    book = null;

                    System.out.println("当前元素名是book");
                } else if (qName.equals("name")) {
                    book.setName(value);
                } else if (qName.equals("author")) {
                    book.setAuthor(value);
                } else if (qName.equals("year")) {
                    book.setYear(value);
                } else if (qName.equals("price")) {
                    book.setPrice(value);
                } else if (qName.equals("language")) {
                    book.setLanguage(value);
                }
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) {
            try {
                super.characters(ch, start, length);
                value = new String(ch, start, length);

                if (!value.trim().equals("")) {
                    System.out.println("当前值是" + value);
                }
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }

        static class SaxBook {

            private String id;
            private String name;
            private String author;
            private String year;
            private String price;
            private String language;

            public String getId() {
                return id;
            }

            public void setId(String id) {
                this.id = id;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public String getAuthor() {
                return author;
            }

            public void setAuthor(String author) {
                this.author = author;
            }

            public String getYear() {
                return year;
            }

            public void setYear(String year) {
                this.year = year;
            }

            public String getPrice() {
                return price;
            }

            public void setPrice(String price) {
                this.price = price;
            }

            public String getLanguage() {
                return language;
            }

            public void setLanguage(String language) {
                this.language = language;
            }

        }

    }

    static class JDom {

        private static ArrayList<SaxDemo.SaxBook> booksList = new ArrayList<>();

        public static void main(String[] args) {
            SAXBuilder saxBuilder = new SAXBuilder();
            try {
                InputStream inputStream = new FileInputStream(FILE_PATH);
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
                org.jdom.Document document = saxBuilder.build(inputStreamReader);
                Element rootElement = document.getRootElement();
                List<Element> bookList = rootElement.getChildren();

                for (Element book : bookList) {
                    SaxDemo.SaxBook bookEntity = new SaxDemo.SaxBook();

                    System.out.println("开始 当前是第" + (bookList.indexOf(book) + 1) + "本书");

                    List<Attribute> attrList = book.getAttributes();

                    for (Attribute attr : attrList) {
                        String attrName = attr.getName();
                        String attrValue = attr.getValue();
                        if (attrName.equals("id")) {
                            bookEntity.setId(attrValue);
                        }

                        System.out.println("属性名是" + attrName + "----属性值是" + attrValue);
                    }

                    List<Element> bookChilds = book.getChildren();

                    for (Element child : bookChilds) {
                        if (child.getName().equals("name")) {
                            bookEntity.setName(child.getValue());
                        } else if (child.getName().equals("author")) {
                            bookEntity.setAuthor(child.getValue());
                        } else if (child.getName().equals("year")) {
                            bookEntity.setYear(child.getValue());
                        } else if (child.getName().equals("price")) {
                            bookEntity.setPrice(child.getValue());
                        } else if (child.getName().equals("language")) {
                            bookEntity.setLanguage(child.getValue());
                        }

                        System.out.println("当前元素名是" + child.getName() + " 当前元素值是" + child.getValue());
                    }

                    booksList.add(bookEntity);
                    bookEntity = null;

                    System.out.println("结束 当前是第" + (bookList.indexOf(book) + 1) + "本书");
                    System.out.println(booksList.size());
                    System.out.println(booksList.get(booksList.size() - 1).getId());
                    System.out.println(booksList.get(booksList.size() - 1).getName());
                }
            } catch (JDOMException | IOException e) {
                e.printStackTrace();
            }
        }
    }

    static class Dom4j {
        public static void main(String[] args) {
            SAXReader reader = new SAXReader();
            try {
                org.dom4j.Document document = reader.read(new File(FILE_PATH));
                org.dom4j.Element bookStore = document.getRootElement();
                Iterator<org.dom4j.Element> it = bookStore.elementIterator();

                while (it.hasNext()) {
                    System.out.println("开始 解析book");

                    org.dom4j.Element book = it.next();
                    List<org.dom4j.Attribute> bookAttrs = book.attributes();

                    for (org.dom4j.Attribute attr : bookAttrs) {
                        System.out.println("book属性名是" + attr.getName() + " 属性值是" + attr.getValue());
                    }

                    Iterator<org.dom4j.Element> it2 = book.elementIterator();

                    while (it2.hasNext()) {
                        org.dom4j.Element bookChild = it2.next();

                        System.out.println("元素名是" + bookChild.getName() + " 元素值是" + bookChild.getStringValue());
                    }
                    System.out.println("结束 解析book");
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            }
        }
    }

    static class Stax {
        public static void main(String[] args) {
            boolean bName = false;
            boolean bAuthor = false;
            boolean bYear = false;
            boolean bPrice = false;
            try {
                XMLInputFactory factory = XMLInputFactory.newInstance();
                XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(FILE_PATH));
                while (eventReader.hasNext()) {
                    XMLEvent event = eventReader.nextEvent();
                    switch (event.getEventType()) {
                        case XMLStreamConstants.START_ELEMENT:
                            StartElement startElement = event.asStartElement();
                            String qName = startElement.getName().getLocalPart();

                            if (qName.equalsIgnoreCase("book")) {
                                Iterator<javax.xml.stream.events.Attribute> attributes = startElement.getAttributes();
                                String id = attributes.next().getValue();

                                System.out.println("Start Element: book");
                                System.out.println("id: " + id);
                            } else if (qName.equalsIgnoreCase("name")) {
                                bName = true;
                            } else if (qName.equalsIgnoreCase("author")) {
                                bAuthor = true;
                            } else if (qName.equalsIgnoreCase("year")) {
                                bYear = true;
                            } else if (qName.equalsIgnoreCase("price")) {
                                bPrice = true;
                            }
                            break;
                        case XMLStreamConstants.CHARACTERS:
                            Characters characters = event.asCharacters();

                            if (bName) {
                                bName = false;

                                System.out.println("Name: " + characters.getData());
                            }
                            if (bAuthor) {
                                bAuthor = false;

                                System.out.println("Author: " + characters.getData());
                            }
                            if (bYear) {
                                bYear = false;

                                System.out.println("Year: " + characters.getData());
                            }
                            if (bPrice) {
                                bPrice = false;

                                System.out.println("Price: " + characters.getData());
                            }
                            break;
                        case XMLStreamConstants.END_ELEMENT:
                            EndElement endElement = event.asEndElement();

                            if (endElement.getName().getLocalPart().equalsIgnoreCase("book")) {
                                System.out.println("End Element: book");
                            }
                            break;
                    }
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (XMLStreamException e) {
                e.printStackTrace();
            }
        }
    }

    static class XPath {
        public static void main(String[] args) {
            try {
                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                File inputFile = new File(FILE_PATH);
                Document doc = dBuilder.parse(inputFile);
                doc.getDocumentElement().normalize();
                javax.xml.xpath.XPath xPath = XPathFactory.newInstance().newXPath();
                String expression = "/bookstore/book";
                NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);

                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node nNode = nodeList.item(i);

                    System.out.println("Current Element :" + nNode.getNodeName());
                    if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                        org.w3c.dom.Element eElement = (org.w3c.dom.Element) nNode;

                        System.out.println("book id : " + eElement.getAttribute("id"));
                        System.out.println("Name : " + eElement.getElementsByTagName("name").item(0).getTextContent());
                        System.out.println("Author : " + eElement.getElementsByTagName("author").item(0).getTextContent());
                        System.out.println("Year : " + eElement.getElementsByTagName("year").item(0).getTextContent());
                        System.out.println("Price : " + eElement.getElementsByTagName("price").item(0).getTextContent());
                    }
                }
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (XPathExpressionException e) {
                e.printStackTrace();
            } catch (SAXException e) {
                e.printStackTrace();
            }
        }
    }

}